package com.videoweb.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.videoweb.mapper.UserMapper;
import com.videoweb.model.User;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;
import java.util.regex.Pattern;

@Slf4j
@Service
public class UserService extends ServiceImpl<UserMapper, User> {
    
    private final PasswordEncoder passwordEncoder;
    private static final Pattern EMAIL_PATTERN = Pattern.compile(
        "^[A-Za-z0-9+_.-]+@(.+)$"
    );
    
    public UserService(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }
    
    public Optional<User> findByUsername(String username) {
        return Optional.ofNullable(this.getOne(new QueryWrapper<User>().eq("username", username)));
    }

    private void validateNewUser(User user) {
        // Username validation
        if (user.getUsername() == null || user.getUsername().trim().isEmpty()) {
            throw new IllegalArgumentException("Username is required");
        }
        if (user.getUsername().length() < 3 || user.getUsername().length() > 50) {
            throw new IllegalArgumentException("Username must be between 3 and 50 characters");
        }
        if (this.getOne(new QueryWrapper<User>().eq("username", user.getUsername())) != null) {
            throw new IllegalArgumentException("Username already exists");
        }

        // Password validation
        if (user.getPassword() == null || user.getPassword().trim().isEmpty()) {
            throw new IllegalArgumentException("Password is required");
        }
        if (user.getPassword().length() < 6 || user.getPassword().length() > 100) {
            throw new IllegalArgumentException("Password must be between 6 and 100 characters");
        }

        // Email validation
        if (user.getEmail() == null || user.getEmail().trim().isEmpty()) {
            throw new IllegalArgumentException("Email is required");
        }
        if (!EMAIL_PATTERN.matcher(user.getEmail()).matches()) {
            throw new IllegalArgumentException("Invalid email format");
        }
        if (this.getOne(new QueryWrapper<User>().eq("email", user.getEmail())) != null) {
            throw new IllegalArgumentException("Email already exists");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public User register(User user) {
        // Trim input fields
        user.setUsername(user.getUsername() != null ? user.getUsername().trim() : null);
        user.setEmail(user.getEmail() != null ? user.getEmail().trim() : null);
        
        // Validate all fields before doing any database operations
        validateNewUser(user);

        try {
            // Encode password and save user
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            if (!this.save(user)) {
                throw new RuntimeException("Failed to register user");
            }
            return user;
        } catch (Exception e) {
            // Convert any unexpected exceptions to RuntimeException to ensure rollback
            throw new RuntimeException("Error registering user: " + e.getMessage(), e);
        }
    }

    public Optional<User> getCurrentUser(String username) {
        try {
            QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq("username", username);
            User user = this.getOne(queryWrapper);
            return Optional.ofNullable(user);
        } catch (Exception e) {
            log.error("Error getting user by username: " + username, e);
            return Optional.empty();
        }
    }
}
